package com.tca.common.web.config;


import com.tca.common.core.bean.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

/**
 * @author zhouan
 * 全局异常控制
 */
@Slf4j
@RestControllerAdvice
@ConditionalOnProperty(value = "tca.web.exception-handler.enabled", havingValue = "true", matchIfMissing = true)
public class ExceptionHandlerAdviceConfig {

    /**
     * 请求方法错误
     * @param e
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result<?> handleMethodNotSupported (HttpRequestMethodNotSupportedException e) {
        log.error("请求方法错误: {}", e);
        Result failure = Result.failure("请求方法错误");
        failure.setCode(400);
        return failure;
    }


    /**
     * 参数类型转换错误
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public Result handleMethodArgumentTypeMismatchException (MethodArgumentTypeMismatchException e) {
        log.error("参数类型转换错误: {}", e);
        Result failure = Result.failure("请求参数有误");
        failure.setCode(400);
        return failure;
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public Result<?> httpRequestParamErrorHandler (HttpMessageNotReadableException e) {
        log.error("{}", e);
        Result failure = Result.failure("错误的请求");
        failure.setCode(400);
        return failure;
    }

    /**
     * 缺少必要参数
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<?> handleMethodArgumentNotValidException (MethodArgumentNotValidException e) {
        log.error("请求缺少必要参数: {}", e);
        String error = e.getBindingResult().getFieldError().getDefaultMessage();
        Result failure = Result.failure(error);
        failure.setCode(400);
        return failure;
    }

    /**
     * 不支持的Content-Type
     * @param e
     * @return
     */
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public Result handleHttpMediaTypeNotSupportedException (HttpMediaTypeNotSupportedException e) {
        log.warn("不支持的Content-Type: {}", e);
        Result failure = Result.failure("不支持的Content-Type");
        failure.setCode(400);
        return failure;
    }

    /**
     * 参数绑定错误
     * @param e
     * @return
     */
    @ExceptionHandler(BindException.class)
    public Result<?> handleValidationError (BindException e) {
        log.error("{}", e);
        Result result = Result.failure(e.getBindingResult().getFieldError().getDefaultMessage());
        result.setCode(400);
        return result;
    }

    /**
     * 服务端异常
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public Result<?> handleInternalServerError (Exception e) {
        log.error("{}", e);
        Result result = Result.failure();
        return result;
    }
}

